_Pragma("once");

#include <list>
#include <mutex>
#include <cstring>
#include <memory>

#include "MemberFunctionAdapter.h"
#include "SingletonTemplate.h"
#include "Workable.h"
#include "DateTimeUtility.h"


enum TaskType {
    ETT_ONCE,
    ETT_CIRCLE,
};


enum SchedulerType {
    EST_SCHEDULER_THREAD_SCHEDULE,
};


typedef DateTimeUtility::ClockTime_t tick_count_t;

struct TaskRecord {
    TaskRecord() {
        memset(this, 0, sizeof( *this ));
    }

    TaskRecord(const TaskletInfo& taskletInfo, tick_count_t nextTriggerTime, tick_count_t interval = tick_count_t(0), TaskType taskType = ETT_ONCE, SchedulerType schedulerType = EST_SCHEDULER_THREAD_SCHEDULE, void* opaque = 0) {
        this->taskId				= 0;

        this->taskletInfo		    = taskletInfo;
        this->nextTriggerTime 		= nextTriggerTime;
        this->interval			    = interval;
        this->taskType			    = taskType;
        this->opaque                = opaque;
        this->schedulerType 	    = schedulerType;

        done = false;
    };

    bool operator==(const TaskRecord& taskRecord)const {
        return taskId == taskRecord.taskId;
    }


    int				        taskId;
    TaskletInfo             taskletInfo;
    TaskType		        taskType;
    tick_count_t		    interval;
    tick_count_t		    nextTriggerTime;  //unit is clock
    SchedulerType           schedulerType;
    void*	                opaque;
    bool                    done;
};

using TaskRecordPtr = std::shared_ptr<TaskRecord>;


//
class TaskScheduler : public Workable<TaskScheduler> {
        typedef std::recursive_mutex MutexType;

    friend class  SingletonTemplate<TaskScheduler>;
public:
    TaskScheduler(const tick_count_t& sleepTickCount = tick_count_t(0));
    ~TaskScheduler(void);

    bool addTask(TaskRecordPtr& taskRecord);
    bool cancelTask(TaskRecordPtr& taskRecord);

    void cancelTask(TaskRecordPtr::weak_type& wptrTaskRecord){
        TaskRecordPtr pTaskRecord = wptrTaskRecord.lock();
        if (pTaskRecord) {
            cancelTask(pTaskRecord);
        }
    }

    void makeOnlyOneTask(TaskRecordPtr::weak_type& wptrTaskRecord, TaskRecord* prawTaskRecord) {
        cancelTask(wptrTaskRecord);

        TaskRecordPtr pTaskRecord(prawTaskRecord);
        addTask(pTaskRecord);
        wptrTaskRecord = pTaskRecord;
    }



    bool initial() ;
    bool uninitial();
    bool doWork();

private:

    typedef std::list<TaskRecordPtr> TaskRecordSet;

    TaskRecordSet						mtaskRecordSet;
    MutexType						    mmutex;

    const TaskRecordSet::iterator		mendIterator;

    TaskRecordPtr					    mpCurrentTaskRecord;

    int							        mrecordIdGenerator;

    tick_count_t		                msleepTickCount;		///真正要睡眠的时间
    tick_count_t		                mleastTickCount;        ///walk over all task, the least time slice.
    tick_count_t		                mtempLeastTickCount;	///离下次调度还有多长时间
    tick_count_t			            mcurrentClockCount; ///线程醒来后的当前时间

    TaskRecordSet	                    mdoTaskSet;
};


using TaskSchedulerSingleton = SingletonTemplate<TaskScheduler>;
